﻿using System;
using System.IO;
using System.Linq;
using System.Text;
using System.Windows.Threading;
using System.Xml;
using MCHelp;
using Microsoft.MediaCenter.Store;
using Microsoft.MediaCenter.Store.MXF;
using MoreEPG.Helper;
using MoreEPG.Model;
using NLog;

namespace MoreEPG.DataAccess
{
    public class MXFWriter
    {
        #region Private Vars

        private TVChannelCollection _TVChannels;
        private TVProgrammeCollection _TVProgrammes;
        private PersonCollection _Persons;
        private KeywordCollection _Keywords;
        private GuideImageCollection _GuideImages;
        private MemoryStream stream;
        private Dispatcher _UIdispatcher;
        private Delegate _delegate;
        private string _output_Path = Environment.CurrentDirectory + @"\tmp\";
        private static Logger logger = NLog.LogManager.GetCurrentClassLogger();
        #endregion

        #region Public Fields

        public ResultCollections Results
        {
            set
            {
                this._TVChannels = value.TVChannels;
                this._TVProgrammes = value.TVprograms;
                this._Persons = value.Persons;
                this._Keywords = value.KeyWords;
                this._GuideImages = value.Images;
            }
        }

        
        public string OutputPath
        {
            set
            {
                this._output_Path = value;
            }
        }

        #endregion

        #region Constructor

        public MXFWriter(Dispatcher UIdispatcher, Delegate _Delegate)
        {
            this._UIdispatcher = UIdispatcher;
            this._delegate = _Delegate;
        }

        #endregion

        #region Private Methods

        /// <summary>
        /// Write a whole lot of header info out to the file
        /// </summary>
        /// <param name="theWriter">The object that writes to the file</param>
        private void writePreamble(XmlTextWriter theWriter)
        {
            theWriter.WriteStartElement("Assembly");
            theWriter.WriteAttributeString("name", "mcepg");
            theWriter.WriteAttributeString("version", "6.1.0.0");
            theWriter.WriteAttributeString("cultureInfo", "");
            theWriter.WriteAttributeString("publicKey", "0024000004800000940000000602000000240000525341310004000001000100B5FC90E7027F67871E773A8FDE8938C81DD402BA65B9201D60593E96C492651E889CC13F1415EBB53FAC1131AE0BD333C5EE6021672D9718EA31A8AEBD0DA0072F25D87DBA6FC90FFD598ED4DA35E44C398C454307E8E33B8426143DAEC9F596836F97C8F74750E5975C64E2189F45DEF46B2A2B1247ADC3652BF5C308055DA9");

            theWriter.WriteStartElement("NameSpace");
            theWriter.WriteAttributeString("name", "Microsoft.MediaCenter.Guide");

            theWriter.WriteStartElement("Type");
            theWriter.WriteAttributeString("name", "Lineup");
            theWriter.WriteEndElement(); // Type Node

            theWriter.WriteStartElement("Type");
            theWriter.WriteAttributeString("name", "Channel");
            theWriter.WriteAttributeString("parentFieldName", "lineup");
            theWriter.WriteEndElement(); // Type Node

            theWriter.WriteStartElement("Type");
            theWriter.WriteAttributeString("name", "Service");
            theWriter.WriteEndElement(); // Type Node

            theWriter.WriteStartElement("Type");
            theWriter.WriteAttributeString("name", "ScheduleEntry");
            theWriter.WriteAttributeString("groupName", "ScheduleEntries");
            theWriter.WriteEndElement(); // Type Node

            theWriter.WriteStartElement("Type");
            theWriter.WriteAttributeString("name", "Program");
            theWriter.WriteEndElement(); // Type Node

            theWriter.WriteStartElement("Type");
            theWriter.WriteAttributeString("name", "Keyword");
            theWriter.WriteEndElement(); // Type Node

            theWriter.WriteStartElement("Type");
            theWriter.WriteAttributeString("name", "KeywordGroup");
            theWriter.WriteEndElement(); // Type Node

            theWriter.WriteStartElement("Type");
            theWriter.WriteAttributeString("name", "Person");
            theWriter.WriteAttributeString("groupName", "People");
            theWriter.WriteEndElement(); // Type Node

            theWriter.WriteStartElement("Type");
            theWriter.WriteAttributeString("name", "ActorRole");
            theWriter.WriteAttributeString("parentFieldName", "program");
            theWriter.WriteEndElement(); // Type Node

            theWriter.WriteStartElement("Type");
            theWriter.WriteAttributeString("name", "DirectorRole");
            theWriter.WriteAttributeString("parentFieldName", "program");
            theWriter.WriteEndElement(); // Type Node

            theWriter.WriteStartElement("Type");
            theWriter.WriteAttributeString("name", "WriterRole");
            theWriter.WriteAttributeString("parentFieldName", "program");
            theWriter.WriteEndElement(); // Type Node

            theWriter.WriteStartElement("Type");
            theWriter.WriteAttributeString("name", "HostRole");
            theWriter.WriteAttributeString("parentFieldName", "program");
            theWriter.WriteEndElement(); // Type Node

            theWriter.WriteStartElement("Type");
            theWriter.WriteAttributeString("name", "GuestActorRole");
            theWriter.WriteAttributeString("parentFieldName", "program");
            theWriter.WriteEndElement(); // Type Node

            theWriter.WriteStartElement("Type");
            theWriter.WriteAttributeString("name", "ProducerRole");
            theWriter.WriteAttributeString("parentFieldName", "program");
            theWriter.WriteEndElement(); // Type Node


            theWriter.WriteStartElement("Type");
            theWriter.WriteAttributeString("name", "GuideImage");
            theWriter.WriteEndElement(); // Type Node

            theWriter.WriteStartElement("Type");
            theWriter.WriteAttributeString("name", "Affiliate");
            theWriter.WriteEndElement(); // Type Node

            theWriter.WriteStartElement("Type");
            theWriter.WriteAttributeString("name", "SeriesInfo");
            theWriter.WriteEndElement(); // Type Node

            theWriter.WriteStartElement("Type");
            theWriter.WriteAttributeString("name", "Season");
            theWriter.WriteEndElement(); // Type Node

            theWriter.WriteEndElement(); // Namespace Node
            theWriter.WriteEndElement(); // Assembly Node


            theWriter.WriteStartElement("Assembly");
            theWriter.WriteAttributeString("name", "mcstore");
            theWriter.WriteAttributeString("version", "6.1.0.0");
            theWriter.WriteAttributeString("cultureInfo", "");
            theWriter.WriteAttributeString("publicKey", "0024000004800000940000000602000000240000525341310004000001000100B5FC90E7027F67871E773A8FDE8938C81DD402BA65B9201D60593E96C492651E889CC13F1415EBB53FAC1131AE0BD333C5EE6021672D9718EA31A8AEBD0DA0072F25D87DBA6FC90FFD598ED4DA35E44C398C454307E8E33B8426143DAEC9F596836F97C8F74750E5975C64E2189F45DEF46B2A2B1247ADC3652BF5C308055DA9");

            theWriter.WriteStartElement("NameSpace");
            theWriter.WriteAttributeString("name", "Microsoft.MediaCenter.Store");

            theWriter.WriteStartElement("Type");
            theWriter.WriteAttributeString("name", "Provider");
            theWriter.WriteEndElement(); // Type Node

            theWriter.WriteStartElement("Type");
            theWriter.WriteAttributeString("name", "UId");
            theWriter.WriteAttributeString("parentFieldName", "target");
            theWriter.WriteEndElement(); // Type Node            

            theWriter.WriteEndElement(); // Namespace Node
            theWriter.WriteEndElement(); // Assembly Node

            theWriter.WriteStartElement("Providers");
            theWriter.WriteStartElement("Provider");
            theWriter.WriteAttributeString("id", "provider1");
            theWriter.WriteAttributeString("name", "Tvm2W7");
            theWriter.WriteAttributeString("displayName", "Tvm2W7");
            theWriter.WriteAttributeString("copyright", "Tvm2W7");
            theWriter.WriteEndElement(); // Provider Node    

            theWriter.WriteEndElement(); // Providers Node

        }


        private void writeLineups(XmlTextWriter theWriter)
        {
            theWriter.WriteStartElement("Lineups");

            theWriter.WriteStartElement("Lineup");
            theWriter.WriteAttributeString("id", "l1");
            theWriter.WriteAttributeString("uid", "!Lineup!" + "Tvm2W7");
            theWriter.WriteAttributeString("name", "Tvm2W7");
            theWriter.WriteAttributeString("primaryProvider", "!MCLineup!MainLineup");

            theWriter.WriteStartElement("channels");
            int count = this._TVChannels.Count;
            for (int i = 0; i < count; i++)
            {
                TVChannel currChannel = this._TVChannels[i];
                theWriter.WriteStartElement("Channel");
                theWriter.WriteAttributeString("uid", currChannel.channelUID());
                theWriter.WriteAttributeString("lineup", "l1");
                theWriter.WriteAttributeString("matchName", currChannel.MatchName);
                theWriter.WriteAttributeString("service", currChannel.id());
                theWriter.WriteAttributeString("number", currChannel.id_.ToString());
                theWriter.WriteEndElement(); // Channel
            }


            theWriter.WriteEndElement(); // Channels

            theWriter.WriteEndElement(); // Line Up

            theWriter.WriteEndElement(); // Line Ups
        }

        private void writeScheduleEntries(XmlTextWriter theWriter)
        {
            logger.Debug("Start Write Schedule Entries");
            int count = this._TVChannels.Count;
            for (int i = 0; i < count; i++)
            {
                TVChannel channel = this._TVChannels[i];
                int run = 0;
                theWriter.WriteStartElement("ScheduleEntries");
                theWriter.WriteAttributeString("service", channel.id());
                var sub = (from p in this._TVProgrammes where p.channel.ToLower() == channel.searchString_ orderby p.startTime ascending select p).ToArray();
                int cnt = sub.Count();
                for (int x = 0; x < cnt; x++)
                {
                    TVProgramme prog = sub[x];
                    theWriter.WriteStartElement("ScheduleEntry");
                    theWriter.WriteAttributeString("program", prog.id.ToString());
                    if (run == 0)
                    {
                        theWriter.WriteAttributeString("startTime", DateTimeToMXFFormat(prog.startTime));
                    }
                    theWriter.WriteAttributeString("duration", prog.duration());
                    if (prog.audioFormat == audioFormats.Stereo)
                    {
                        theWriter.WriteAttributeString("isStereo", "1");
                    }
                    int audio = (int)prog.audioFormat;
                    theWriter.WriteAttributeString("audioFormat", audio.ToString());

                    if (prog.isHDTV)
                    {
                        theWriter.WriteAttributeString("isHdtv", "1");
                    }
                    else if (channel.isHDTV)
                    {
                        theWriter.WriteAttributeString("isHdtv", "1");
                    }

                    if (prog.isRepeat)
                    {
                        theWriter.WriteAttributeString("isRepeat", "1");
                    }
                    if (prog.isLive)
                    {
                        theWriter.WriteAttributeString("isLive", "1");
                    }
                    if (prog.isSports)
                    {
                        theWriter.WriteAttributeString("isSports", "1");
                    }
                    if (prog.isLiveSports)
                    {
                        theWriter.WriteAttributeString("isLiveSports", "1");
                    }
                    theWriter.WriteEndElement(); // ScheduleEntry
                    run++;
                }
                theWriter.WriteEndElement(); // ScheduleEntries

            }
            logger.Debug("Stop Write Schedule Entries");
        }

        private void writeServices(XmlTextWriter theWriter)
        {
            theWriter.WriteStartElement("Services");
            int count = this._TVChannels.Count;
            for (int i = 0; i < count; i++)
            {
                TVChannel chan = this._TVChannels[i];
                theWriter.WriteStartElement("Service");
                theWriter.WriteAttributeString("id", chan.id());
                theWriter.WriteAttributeString("uid", chan.uid());
                if (Properties.Settings.Default.CFSuffix)
                {
                    chan.name_ = chan.name_ + " CF";
                }
                theWriter.WriteAttributeString("name", chan.name_);
                theWriter.WriteAttributeString("callSign", chan.callsign());
                theWriter.WriteAttributeString("affiliate", chan.affiliate());
                if (chan.logoUrlID != "-1")
                {
                    theWriter.WriteAttributeString("logoImage", chan.logoUrlID);
                }
                theWriter.WriteEndElement(); // Service
            }
            theWriter.WriteEndElement(); // Services
        }

        private void writeAffiliates(XmlTextWriter theWriter)
        {
            theWriter.WriteStartElement("Affiliates");
            theWriter.WriteStartElement("Affiliate");
            theWriter.WriteAttributeString("name", "Tvm2W7");
            theWriter.WriteAttributeString("uid", "!Affiliate!Tvm2W7");
            //theWriter.WriteAttributeString("logoImage", "i100");
            theWriter.WriteEndElement(); // Affiliate
            theWriter.WriteEndElement(); // Affiliates
        }

        private void writePrograms(XmlTextWriter theWriter)
        {
            theWriter.WriteStartElement("Programs");
            logger.Debug("Start Write Programs");
            var sub = (from p in this._TVProgrammes orderby p.channel, p.startTime ascending select p).ToArray();
            int cnt = sub.Count();
            for (int x = 0; x < cnt; x++)
            {
                TVProgramme prog = sub[x];

                //var pers = (from ac in this.Persons where prog.Persons.Contains(ac.id()) orderby ac.id_ ascending select ac).ToArray();

                var Actors = prog.ActorRoles.ToArray().OrderBy(a => a).ToArray();//(from ac in pers where  ac.Role == Roles.ActorRole orderby ac.id_ ascending select ac).ToArray();
                var Writers = prog.WriterRoles.ToArray().OrderBy(a => a).ToArray();//(from ac in pers where ac.Role == Roles.WriterRole orderby ac.id_ ascending select ac).ToArray();
                var GuestActors = prog.GuestActorRoles.ToArray().OrderBy(a => a).ToArray();//(from ac in pers where ac.Role == Roles.GuestActorRole orderby ac.id_ ascending select ac).ToArray();
                var Hosts = prog.HostRoles.ToArray().OrderBy(a => a).ToArray();//(from ac in pers where ac.Role == Roles.HostRole orderby ac.id_ ascending select ac).ToArray();
                var Producers = prog.ProducerRoles.ToArray().OrderBy(a => a).ToArray();//(from ac in pers where ac.Role == Roles.ProducerRole orderby ac.id_ ascending select ac).ToArray();
                var Directors = prog.DirectorRoles.ToArray().OrderBy(a => a).ToArray();//(from ac in pers where ac.Role == Roles.DirectorRole orderby ac.id_ ascending select ac).ToArray();

                theWriter.WriteStartElement("Program");
                theWriter.WriteAttributeString("id", prog.id.ToString());
                theWriter.WriteAttributeString("uid", prog.uid);
                theWriter.WriteAttributeString("title", prog.title);
                theWriter.WriteAttributeString("description", prog.description);
                if (prog.shortDescription != string.Empty && prog.shortDescription != null)
                {
                    theWriter.WriteAttributeString("shortDescription", prog.shortDescription);
                }
                theWriter.WriteAttributeString("keywords", prog.keywords);
                theWriter.WriteAttributeString("halfStars", prog.halfStars);
                theWriter.WriteAttributeString("episodeTitle", prog.episodeTitle);
                int mpaa = (int)prog.rating;
                theWriter.WriteAttributeString("mpaaRating", mpaa.ToString());

                if (prog.isMovie)
                {
                    theWriter.WriteAttributeString("isMovie", "1");
                }
                if (prog.isKids)
                {
                    theWriter.WriteAttributeString("isKids", "1");
                }
                if (prog.isNews)
                {
                    theWriter.WriteAttributeString("isNews", "1");
                }
                if (prog.isSports)
                {
                    theWriter.WriteAttributeString("isSports", "1");
                }
                if (prog.isSpecial)
                {
                    theWriter.WriteAttributeString("isSpecial", "1");
                }
                if (prog.guideImageID != string.Empty && prog.guideImageID != null)
                {
                    theWriter.WriteAttributeString("guideImage", prog.guideImageID);
                }
                if (prog.isSeries)
                {
                    theWriter.WriteAttributeString("isSeries", "1");
                }
                if (prog.isRepeat)
                {
                    theWriter.WriteAttributeString("originalAirdate", DateTimeToMXFFormat(prog.originalAirdate, true));
                }

                if (Directors.Count() > 0)
                {
                    int ct = Directors.Count();
                    int y = 1;
                    for (int a = 0; a < ct; a++)
                    {
                        string p = (string)Directors[a];
                        theWriter.WriteStartElement("DirectorRole");
                        theWriter.WriteAttributeString("person", p);
                        theWriter.WriteAttributeString("rank", y.ToString());
                        theWriter.WriteEndElement(); // Director Role 
                        y++;
                    }
                }
                if (Actors.Count() > 0)
                {
                    int ct = Actors.Count();
                    int y = 1;
                    for (int a = 0; a < ct; a++)
                    {
                        string p = (string)Actors[a];
                        string[] pp = p.Split(";".ToCharArray());
                        theWriter.WriteStartElement("ActorRole");
                        theWriter.WriteAttributeString("person", pp[0]);
                        theWriter.WriteAttributeString("character", pp[1]);
                        theWriter.WriteAttributeString("rank", y.ToString());
                        theWriter.WriteEndElement(); // Actor Role  
                        y++;
                    }
                }
                if (Writers.Count() > 0)
                {
                    int ct = Writers.Count();
                    int y = 1;
                    for (int a = 0; a < ct; a++)
                    {
                        string p = (string)Writers[a];
                        theWriter.WriteStartElement("WriterRole");
                        theWriter.WriteAttributeString("person", p);
                        theWriter.WriteAttributeString("rank", y.ToString());
                        theWriter.WriteEndElement(); // Writer Role  
                        y++;
                    }
                }
                if (GuestActors.Count() > 0)
                {
                    int ct = GuestActors.Count();
                    int y = 1;
                    for (int a = 0; a < ct; a++)
                    {
                        string p = (string)GuestActors[a];
                        theWriter.WriteStartElement("GuestActorRole");
                        theWriter.WriteAttributeString("person", p);
                        theWriter.WriteAttributeString("rank", y.ToString());
                        theWriter.WriteEndElement(); // GuestActor Role
                        y++;
                    }
                }
                if (Hosts.Count() > 0)
                {
                    int ct = Hosts.Count();
                    int y = 1;
                    for (int a = 0; a < ct; a++)
                    {
                        string p = (string)Hosts[a];
                        theWriter.WriteStartElement("HostRole");
                        theWriter.WriteAttributeString("person", p);
                        theWriter.WriteAttributeString("rank", y.ToString());
                        theWriter.WriteEndElement(); // Host Role
                        y++;
                    }
                }
                if (Producers.Count() > 0)
                {
                    int ct = Producers.Count();
                    int y = 1;
                    for (int a = 0; a < ct; a++)
                    {
                        string p = (string)Producers[a];
                        theWriter.WriteStartElement("ProducerRole");
                        theWriter.WriteAttributeString("person", p);
                        theWriter.WriteAttributeString("rank", y.ToString());
                        theWriter.WriteEndElement(); // Producer Role
                        y++;
                    }
                }

                theWriter.WriteEndElement(); // Program
            }
            theWriter.WriteEndElement(); // Programs
            logger.Debug("Stop Write Programs");
        }

        private void writeSeasons(XmlTextWriter theWriter)
        {
            theWriter.WriteStartElement("Seasons");
            /* 
                theWriter.WriteStartElement("Season");
                theWriter.WriteAttributeString("id","sn1");
                theWriter.WriteAttributeString("uid","!Season!164959780");
                theWriter.WriteAttributeString("series","si1");
                theWriter.WriteAttributeString("title","24: Season 05");
                theWriter.WriteAttributeString("year","2009");
                theWriter.WriteEndElement(); // Season
             */
            theWriter.WriteEndElement(); // Seasons
        }

        private void writeSeries(XmlTextWriter theWriter)
        {
            theWriter.WriteStartElement("SeriesInfos");

            /*  Example for reference:
                theWriter.WriteStartElement("SeriesInfo");
                theWriter.WriteAttributeString("id", "si1");
                theWriter.WriteAttributeString("uid", "!Series!24");
                theWriter.WriteAttributeString("title", "24");
                theWriter.WriteAttributeString("shortTitle", "24");
                theWriter.WriteAttributeString("description", "Jack Bower does cool stuff.");
                theWriter.WriteAttributeString("shortDescription", "24.  Cool.");
                theWriter.WriteAttributeString("startAirdate", "2009-01-01T00:00:00");
                theWriter.WriteAttributeString("endAirdate", "2010-01-01T00:00:00");
                theWriter.WriteAttributeString("guideImage", "i100");
                theWriter.WriteEndElement(); // Series Info
             */
            theWriter.WriteEndElement(); // Series Infos
        }

        private void writePeople(XmlTextWriter theWriter)
        {
            logger.Debug("Start write People");
            theWriter.WriteStartElement("People");
            int count = this._Persons.Count;
            for (int i = 0; i < count; i++)
            {
                Person p = this._Persons[i];
                theWriter.WriteStartElement("Person");
                theWriter.WriteAttributeString("id", p.id());
                theWriter.WriteAttributeString("name", p.name);
                theWriter.WriteAttributeString("uid", p.Uid);
                theWriter.WriteEndElement(); // Person
            }

            theWriter.WriteEndElement(); // People
            logger.Debug("Stop write People");
        }

        private void writeImages(XmlTextWriter theWriter)
        {
            logger.Debug("Start write Images");
            theWriter.WriteStartElement("GuideImages");

            int count = this._GuideImages.Count;
            for (int i = 0; i < count; i++)
            {
                GuideImage img = this._GuideImages[i];
                theWriter.WriteStartElement("GuideImage");
                theWriter.WriteAttributeString("id", img.Id());
                theWriter.WriteAttributeString("uid", img.Uid);
                theWriter.WriteAttributeString("imageUrl", img.Url);
                theWriter.WriteEndElement(); // Guide Image
            }


            theWriter.WriteEndElement(); // Guide Images
            logger.Debug("Stop write Images");
        }

        private void writeKeywords(XmlTextWriter theWriter)
        {
            logger.Debug("Start write Keywords");
            theWriter.WriteStartElement("Keywords");
            int count = this._Keywords.Count;
            for (int i = 0; i < count; i++)
            {
                Keyword key = this._Keywords[i];
                theWriter.WriteStartElement("Keyword");
                theWriter.WriteAttributeString("id", key.Id());
                theWriter.WriteAttributeString("word", key.Word);
                theWriter.WriteEndElement(); // Keyword Node
            }
            theWriter.WriteEndElement(); // Keywords


            theWriter.WriteStartElement("KeywordGroups");


            theWriter.WriteStartElement("KeywordGroup");
            theWriter.WriteAttributeString("uid", "!KeywordGroup!k1");
            theWriter.WriteAttributeString("groupName", "k1");
            theWriter.WriteAttributeString("keywords", "k100");
            theWriter.WriteEndElement(); // Keyword Group

            theWriter.WriteEndElement(); // Keyword Groups
            logger.Debug("Start write Keywords");
        }

        /// <summary>
        /// Convert a DateTime object into the correct string format for MXF files
        /// </summary>
        /// <param name="theDateTime"></param>
        /// <returns>A String in the MXF date time format</returns>
        private string DateTimeToMXFFormat(DateTime theDateTime)
        {
            return theDateTime.ToString("yyyy-MM-ddTHH:mm:ss");
        }

        /// <summary>
        /// Convert a DateTime object into the correct string format for MXF files (LocalTime)
        /// </summary>
        /// <param name="theDateTime"></param>
        /// <returns>A String in the MXF date time format</returns>
        /// 
        private string DateTimeToMXFFormat(DateTime theDateTime, bool localTime)
        {
            return theDateTime.ToString("yyyy-MM-ddTHH:mm:ss");
        }

        private bool _UpdateProgress(int percentage)
        {
            this._UIdispatcher.BeginInvoke(this._delegate, percentage / 10);
            return true;
        }

        private void WriteMXFFileToDisk(string outputFileName)
        {

            if (this.stream != null)
            {
                try
                {
                    //string outputFileName = this.output_Path + @"output.MXF";
                    if (File.Exists(outputFileName))
                    {
                        File.Delete(outputFileName);
                    }
                    FileStream fs = File.OpenWrite(outputFileName);
                    this.stream.WriteTo(fs);
                    this.stream.Close();
                    this.stream.Dispose();
                    fs.Close();
                    fs.Dispose();
                }
                catch
                {

                }
                finally
                {
                    this.stream.Close();
                    this.stream.Dispose();
                }
            }
        }

        private string LoadEPG()
        {
            string error = string.Empty;

            if (this.stream != null)
            {
                try
                {
                    ObjectStore store = new MCConnection().Store;
                    MxfImporter.Import(stream, store, new MxfImporter.ImportProgress(_UpdateProgress));
                    store.Dispose();
                }
                catch (Exception ex)
                {
                    error = ex.Message;
                }
                finally
                {
                    this.stream.Close();
                    this.stream.Dispose();
                }
            }
            else
            {
                error = "Stream ist nicht initialisiert!";
            }
            return error;
        }

        #endregion

        #region Public Methods

        public void Write(bool LoadInMC, bool WriteToFile)
        {
            if (_TVChannels == null || _TVProgrammes == null || _Persons == null || _Keywords == null || _GuideImages == null)
            {
                logger.Error("One or More Data Fields are null");
                throw new Exception("One or More Data Fields are null");
            }

            this.stream = new MemoryStream();
            XmlTextWriter xmlWriter = new XmlTextWriter(this.stream, Encoding.UTF8);
            xmlWriter.Formatting = Formatting.Indented; // make it pretty

            // kick things off
            xmlWriter.WriteStartDocument();
            xmlWriter.WriteStartElement("MXF");
            xmlWriter.WriteAttributeString("xmlns:sql", "urn:schemas-microsoft-com:xml-sql");
            xmlWriter.WriteAttributeString("xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance");

            // there is a bunch of stuff that we write as a header
            writePreamble(xmlWriter);
            xmlWriter.WriteStartElement("With");
            xmlWriter.WriteAttributeString("provider", "provider1");

            // keywords for grouping and searching
            this.writeKeywords(xmlWriter);

            // images for channels/series/programs
            this.writeImages(xmlWriter);

            // actors etc
            this.writePeople(xmlWriter);

            // series info
            this.writeSeries(xmlWriter);

            // seasons ,the parent of series
            this.writeSeasons(xmlWriter);

            // the TV program info
            this.writePrograms(xmlWriter);

            // who is providing the listings (Us!)
            this.writeAffiliates(xmlWriter);

            // channel info
            this.writeServices(xmlWriter);


            // when the programs are aired
            this.writeScheduleEntries(xmlWriter);

            // more channel stuff really
            this.writeLineups(xmlWriter);


            // finish up
            xmlWriter.WriteEndElement(); // with
            xmlWriter.WriteEndElement(); // root MXF Node

            logger.Debug("MXF File wird geschlossen !");
            // done!

            xmlWriter.Flush();
            this.stream.Position = 0;
            if (LoadInMC)
            {
                this.LoadEPG();
            }
            if (WriteToFile)
            {
                string outputFileName = this._output_Path + @"output.MXF";
                this.WriteMXFFileToDisk(outputFileName);
            }

        }

        #endregion
    }
}
